﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.Metadata.Entity;

namespace T.FAS.Runtime.Metadata.Entity.DataModel
{
    public partial class EntityObject
    {
        public const string RefSchemaPrefix = "Schema.EO";
        public const string RefSchemaAttrAlias = "Attrs";
        /// <summary>
        /// 构建TSchema
        /// </summary>
        /// <returns></returns>
        public TSchema BuildSchema()
        {
            TSchema schema = new TSchema
            {
                MetadataType = TEntityType.EO,
            };
            schema.Entity = BuildTEntity(this);
            return schema;
        }

        public override IRefSchemaEntity BuildRefSchema()
        {
            try
            {
                var eo = this;
                EntityObjectRefSchemaEntity schema = new EntityObjectRefSchemaEntity
                {
                    ID = eo.ID,
                    Code = eo.Code,
                    Name = eo.Name,
                    Attrs = new Dictionary<string, EntityObjectRefSchemaEntity.Attr>()
                };
                foreach (var attr in eo.EntityObjectAttributes)
                {
                    schema.Attrs[attr.Code] = EntityObjectRefSchemaEntity.Attr.Mapping(eo, attr);
                }
                return schema;
            }
            catch (Exception e)
            {
                throw new Exception($"cdo:{Code}构造RefSchema失败, msg:{e.Message}", e);
            }
        }

        /// <summary>
        /// 递归将树结构EO转化为以TSchema为入口的VM结构
        /// </summary>
        /// <param name="eo">EO</param>
        /// <returns>递归时用到的返回值，调用方不需要直接用</returns>
        private TEntity BuildTEntity(EntityObject eo, int depth = 0, string parentRefSchemaExpr = null)
        {
            Type type = typeof(DataType);
            #region 当前CNO节点转换为TEntity
            TEntity entity = new TEntity
            {
                MetadataID = eo.ID,                             //EO.ID
                MetadataCode = eo.Code,                         //结果集表名，设计时已配好
                MetadataName = eo.Name,                         //EO.Name
                RefSchemaExpr = $"{RefSchemaPrefix}.{eo.Code}", 
                MetadataType = TEntityType.EO,                  //类型都设置为DO
                Description = eo.Name,                          //
                Attributes = new List<TAttribute>(),            //结果集Table列集合，映射EO Attrs
            };
            //将列EO.Attributes映射为结果集中的列
            foreach (var attr in eo.EntityObjectAttributes.OrderBy(o => o.Sort))
            {
                TAttribute tattr = new TAttribute
                {
                    ID = attr.ID,                                                   //【暂时用不到】
                    Code = attr.Code,                                               // 结果集列名，默认为EO.Attr.Code
                    Name = attr.Name,                                               // 展示用中文名
                    RefSchemaExpr = $"{entity.RefSchemaExpr}.{RefSchemaAttrAlias}.{attr.Code}",
                    Description = attr.Description,                                 // EO列说明 
                    Length = attr.Length,
                    Precision = attr.Precision,
                    IsRequired = !attr.IsNullable,
                    SortOrder = attr.Sort,                                          // 排序
                    ExtProperties = new Dictionary<string, object>(),
                };
                if (!string.IsNullOrEmpty(attr.RelatedEntityObjectID)) 
                {
                    if (attr.IsList)
                    {
                        tattr.DataType = DataType.List;
                    }
                    else
                    {
                        tattr.DataType = DataType.Record;
                    }
                    if (attr.SubEntity == null)
                    {
                        //throw new FasException(DataModelErrorCode.EO.BuildSchemaError, $"EO:{EO.Code}元数据获取指定属性:{attr.Code}的关联EO:{attr.RelatedEntityObjectID}的实例失败");
                    }
                    else
                    {
                        tattr.Entity = BuildTEntity(attr.SubEntity, depth + 1, entity.RefSchemaExpr); //递归处理Sub EO
                        tattr.Entity.ResultType = tattr.DataType;                     //父级节点数据类型跟子节点ResultType一致
                        /************EO不需要处理Relation，Relation是做数据表结果集转化为结构化存储的标记*************/
                        tattr.Entity.Relation = new TEntityRelation                 //添加Sub EO的Relation信息
                        {
                            ID = Guid.NewGuid().ToString(),                         //暂时用不到
                            FromTEntityCode = eo.Code,                              //父结果集code, EO.Code
                            FromTAttributeCode = attr.Code,                         //父结果集主键列
                            ToTEntityCode = tattr.Entity.MetadataCode,              //当前节点的结果集的表名 Table Name
                            ToTAttributeCode = tattr.Entity.Attributes.FirstOrDefault().Code,//当前节点外键列的映射列名
                        };
                    }
                    tattr.OriginDataType = attr.DataType;
                    tattr.ExtProperties["RefMetaType"] = DataModelConst.EOMetaType;
                }
                else
                {
                    tattr.DataType = (DataType)Enum.Parse(type, attr.DataType, true);   // 普通数据类型
                }
                entity.Attributes.Add(tattr);
            }
            #endregion

            return entity;
        }
    }
}
